home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Resources / Online / Term / Extras / Source / term-source.lha / CustomRequest.c < prev    next >
C/C++ Source or Header  |  1996-10-20  |  19KB  |  784 lines

  1. /*
  2. **    CustomRequest.c
  3. **
  4. **    EasyRequest like custom requester
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16.     /* GetScreenInfo():
  17.      *
  18.      *    Obtain the currently visible screen area.
  19.      */
  20.  
  21. STATIC VOID
  22. GetScreenInfo(struct Screen *Screen,WORD *Left,WORD *Top,WORD *Width,WORD *Height)
  23. {
  24.     struct ViewPortExtra    *Extra;
  25.     struct TagItem             Tags[2] = { VTAG_VIEWPORTEXTRA_GET, NULL, TAG_DONE };
  26.  
  27.     if(!VideoControl(Screen->ViewPort.ColorMap,Tags))
  28.         Extra = (struct ViewPortExtra *)Tags[0].ti_Data;
  29.     else
  30.         Extra = NULL;
  31.  
  32.     if(Extra)
  33.     {
  34.         struct Rectangle Clip;
  35.  
  36.         QueryOverscan(GetVPModeID(&Screen->ViewPort),&Clip,OSCAN_TEXT);
  37.  
  38.         *Width    = Extra->DisplayClip.MaxX - Extra->DisplayClip.MinX + 1;
  39.         *Height    = Extra->DisplayClip.MaxY - Extra->DisplayClip.MinY + 1;
  40.  
  41.         if(*Width < Clip.MaxX - Clip.MinX + 1)
  42.             *Width = Clip.MaxX - Clip.MinX + 1;
  43.  
  44.         if(*Height < Clip.MaxY - Clip.MinY + 1)
  45.             *Height = Clip.MaxY - Clip.MinY + 1;
  46.     }
  47.     else
  48.     {
  49.         *Width    = Screen->Width;
  50.         *Height    = Screen->Height;
  51.     }
  52.  
  53.     *Left    = ABS(Screen->LeftEdge);
  54.     *Top    = ABS(Screen->TopEdge);
  55.  
  56.     if(*Left > Screen->Width || *Left < 0)
  57.         *Left = 0;
  58.  
  59.     if(*Top > Screen->Height || *Top < 0)
  60.         *Top = 0;
  61. }
  62.  
  63.     /* CentreWindow():
  64.      *
  65.      *    Centre a window within the visible bounds of
  66.      *    a screen.
  67.      */
  68.  
  69. STATIC VOID
  70. CentreWindow(struct Screen *Screen,WORD Width,WORD Height,WORD *Left,WORD *Top)
  71. {
  72.     WORD ScreenWidth,ScreenHeight,ScreenLeft,ScreenTop;
  73.  
  74.     GetScreenInfo(Screen,&ScreenLeft,&ScreenTop,&ScreenWidth,&ScreenHeight);
  75.  
  76.     *Left    = ScreenLeft + (ScreenWidth - Width) / 2;
  77.     *Top    = ScreenTop + (ScreenHeight - Height) / 2;
  78. }
  79.  
  80. VOID SAVE_DS ASM
  81. CustomStuffText(REG(a3) LONG *Data,REG(d0) UBYTE Char)
  82. {
  83.     struct IntuiText *IText;
  84.     STRPTR Buffer;
  85.  
  86.     Buffer    = (STRPTR)Data[0];    /* Space allocated for the char buffer */
  87.     IText    = (APTR)Data[1];    /* Space allocated for the IntuiTexts */
  88.  
  89.     if(Char == Data[2] || Char == '\0')
  90.     {
  91.         LONG Width;
  92.  
  93.         IText->LeftEdge    = 0;
  94.         IText->TopEdge    = Data[3];    /* Text top edge */
  95.         IText->ITextFont    = NULL;
  96.  
  97.             /* Line height, derived from font size */
  98.  
  99.         Data[3] += Data[4];
  100.  
  101.             /* Chop off the rest */
  102.  
  103.         *Buffer++ = '\0';
  104.  
  105.             /* Measure the length in pixels */
  106.  
  107.         if(Data[6])
  108.         {
  109.             Width = TextLength((APTR)Data[6],IText->IText,(LONG)Buffer - (LONG)IText->IText - 1);
  110.  
  111.                 /* More than we got before? */
  112.  
  113.             if(Width > Data[5])
  114.                 Data[5] = Width;
  115.         }
  116.  
  117.         if(Char != '\0')
  118.         {
  119.                 /* Link to following text */
  120.  
  121.             IText->NextText = IText + 1;
  122.  
  123.                 /* Get ready for the next line */
  124.  
  125.             Data[1] = (LONG)(++IText);
  126.  
  127.                 /* Start of next line */
  128.  
  129.             IText->IText = Buffer;
  130.         }
  131.         else
  132.             IText->NextText = NULL;            /* Terminate the chain */
  133.     }
  134.     else
  135.         *Buffer++ = Char;                        /* Just store the character */
  136.  
  137.     Data[0] = (LONG)Buffer;                        /* Remember for next char */
  138. }
  139.  
  140. VOID ASM
  141. CustomCountChar(REG(a3) LONG *Count,REG(d0) UBYTE Char)
  142. {
  143.     if(Char == Count[2] || Char == '\0')    /* Count the number of lines */
  144.         Count[1]++;
  145.  
  146.     Count[0]++;                                /* Count the number of characters in total */
  147. }
  148.  
  149. STATIC struct IntuiText *
  150. BuildITextTable(STRPTR FormatString,va_list VarArgs,UBYTE Terminator,LONG *Information,LONG *MoreData)
  151. {
  152.     struct IntuiText *Primitive;
  153.  
  154.     Information[0] = Information[1] = 0;
  155.     Information[2] = Terminator;
  156.  
  157.     #ifdef USE_GLUE
  158.         RawDoFmt(FormatString,(APTR)VarArgs,(PUTCHAR)CustomCountCharGlue,(APTR)Information);
  159.     #else
  160.         RawDoFmt(FormatString,(APTR)VarArgs,(PUTCHAR)CustomCountChar,(APTR)Information);
  161.     #endif
  162.  
  163.     if(Primitive = (struct IntuiText *)AllocVec(Information[1] * sizeof(struct IntuiText) + Information[0],MEMF_ANY))
  164.     {
  165.             /* Room for the char buffer */
  166.  
  167.         MoreData[0]    = (LONG)(Primitive + Information[1]);
  168.  
  169.             /* Room for the IntuiTexts */
  170.  
  171.         MoreData[1] = (LONG)Primitive;
  172.  
  173.             /* Separator char to use */
  174.  
  175.         MoreData[2] = Terminator;
  176.  
  177.             /* Top edge of first text, the following lines get placed below */
  178.  
  179.         MoreData[3] = 0;
  180.  
  181.             /* The maximum width of all lines will end up here */
  182.  
  183.         MoreData[5] = 0;
  184.  
  185.             /* Now this is important; the first IText buffer must */
  186.             /* be set up here, the formatting code will do the rest */
  187.             /* for all the others */
  188.  
  189.         Primitive[0].IText = (STRPTR)MoreData[0];
  190.     }
  191.  
  192.     return(Primitive);
  193. }
  194.  
  195.     /* ShowInfo():
  196.      *
  197.      *    Display an EasyRequest like information requester.
  198.      */
  199.  
  200. LONG
  201. ShowInfo(struct Window *Parent,STRPTR Title,STRPTR Continue,STRPTR FormatString,...)
  202. {
  203.     struct Screen *Screen;
  204.     ULONG IntuiLock;
  205.     LONG Result;
  206.     BOOL PopBack;
  207.  
  208.     Result = 0;
  209.  
  210.     if(Parent)
  211.         Screen = Parent->WScreen;
  212.     else
  213.         Screen = LockPubScreen(NULL);
  214.  
  215.     IntuiLock = LockIBase(NULL);
  216.  
  217.     PopBack = (BOOL)(IntuitionBase->FirstScreen != Screen);
  218.  
  219.     UnlockIBase(IntuiLock);
  220.  
  221.     if(Screen)
  222.     {
  223.         struct DrawInfo *DrawInfo;
  224.  
  225.         if(PopBack)
  226.             ScreenToFront(Screen);
  227.  
  228.         if(DrawInfo = GetScreenDrawInfo(Screen))
  229.         {
  230.             LONG Information[3],GadgetInformation[3];
  231.             LONG MoreData[7],GadgetData[7];
  232.             struct Image *GadgetFrameImage;
  233.             struct IntuiText *GadgetText;
  234.             struct TextAttr FontTemplate;
  235.             struct Gadget **GadgetTable;
  236.             struct IntuiText *BodyText;
  237.             struct TextFont *Font;
  238.             LONG FullButtonWidth;
  239.             LONG DistX,DistY;
  240.             LONG RoomX,RoomY;
  241.             va_list VarArgs;
  242.  
  243.                 /* We'll need this one later */
  244.  
  245.             Font = DrawInfo->dri_Font;
  246.  
  247.                 /* Set up the spacing information */
  248.  
  249.             RoomY = (Font->tf_YSize + 1) / 2;
  250.             RoomX = (RoomY * DrawInfo->dri_Resolution.Y) / DrawInfo->dri_Resolution.X;
  251.  
  252.                 /* Make a copy of the screen font */
  253.  
  254.             AskFont(&Screen->RastPort,&FontTemplate);
  255.  
  256.                 /* Request that it be boldfaced, the leftmost */
  257.                 /* button will receive this type of label */
  258.  
  259.             FontTemplate.ta_Style |= FSF_BOLD;
  260.  
  261.             va_start(VarArgs,FormatString);
  262.             BodyText = BuildITextTable(FormatString,VarArgs,'\n',Information,MoreData);
  263.             va_end(VarArgs);
  264.  
  265.             GadgetText = BuildITextTable(Continue,NULL,'|',GadgetInformation,GadgetData);
  266.  
  267.             GadgetTable = (struct Gadget **)AllocVec(sizeof(struct Gadget *) * GadgetInformation[1],MEMF_ANY|MEMF_CLEAR);
  268.  
  269.             GadgetFrameImage = (struct Image *)NewObjectA(NULL,FRAMEICLASS,NULL);
  270.  
  271.             if(GadgetFrameImage && GadgetTable && GadgetText)
  272.             {
  273.                 struct Gadget *Previous;
  274.                 LONG ID,Last,i;
  275.                 ULONG PrevTag;
  276.  
  277.                 ID            = 0;
  278.                 Last        = GadgetInformation[1] - 1;
  279.  
  280.                 Previous    = NULL;
  281.                 PrevTag        = TAG_IGNORE;
  282.  
  283.                     /* We'll work with the button sizes in a minute... */
  284.  
  285.                 FullButtonWidth = 0;
  286.  
  287.                     /* We don't want fonts to be measured */
  288.  
  289.                 GadgetData[6] = 0;
  290.  
  291.                 #ifdef USE_GLUE
  292.                     RawDoFmt(Continue,NULL,(PUTCHAR)CustomStuffTextGlue,GadgetData);
  293.                 #else
  294.                     RawDoFmt(Continue,NULL,(PUTCHAR)CustomStuffText,GadgetData);
  295.                 #endif    /* USE_GLUE */
  296.  
  297.                 DistY = 2;
  298.                 DistX = (DistY * DrawInfo->dri_Resolution.Y) / DrawInfo->dri_Resolution.X;
  299.  
  300.                 GadgetText[0].ITextFont = &FontTemplate;
  301.  
  302.                 for(i = 0 ; i <= Last ; i++)
  303.                 {
  304.                     if(i == Last)
  305.                         ID = 0;
  306.                     else
  307.                         ID++;
  308.  
  309.                     GadgetText[i].NextText = NULL;
  310.  
  311.                     if(GadgetTable[i] = NewObject(NULL,FRBUTTONCLASS,
  312.                         GA_IntuiText,    &GadgetText[i],
  313.                         GA_Image,        GadgetFrameImage,
  314.                         GA_RelVerify,    TRUE,
  315.                         GA_ID,            ID,
  316.                         GA_DrawInfo,    DrawInfo,
  317.                         PrevTag,        Previous,
  318.                     TAG_DONE))
  319.                     {
  320.                         Previous    = GadgetTable[i];
  321.                         PrevTag        = GA_Previous;
  322.  
  323.                         SetAttrs(Previous,
  324.                             GA_Width,    2*DistX + Previous->Width,
  325.                             GA_Height,    2*DistY + Previous->Height,
  326.                             GA_DrawInfo,DrawInfo,
  327.                         TAG_DONE);
  328.  
  329.                             /* Add the width of the button, plus */
  330.                             /* some room in between */
  331.  
  332.                         FullButtonWidth += Previous->Width + RoomX;
  333.                     }
  334.                     else
  335.                     {
  336.                         LONG j;
  337.  
  338.                         for(j = 0 ; j < i ; j++)
  339.                             DisposeObject(GadgetTable[i]);
  340.  
  341.                         FreeVec(GadgetTable);
  342.                         GadgetTable = NULL;
  343.  
  344.                         break;
  345.                     }
  346.                 }
  347.  
  348.                     /* Subtract the trailing space, add the border space */
  349.  
  350.                 FullButtonWidth += Screen->WBorRight + RoomX + Screen->WBorLeft;
  351.             }
  352.  
  353.                 /* Did we get what we wanted and will the buttons fit on */
  354.                 /* the screen? */
  355.  
  356.             if(BodyText && GadgetText && GadgetTable && FullButtonWidth <= Screen->Width)
  357.             {
  358.                 WORD WindowWidth,WindowHeight,ScreenWidth,ScreenHeight,ScreenLeft,ScreenTop;
  359.                 struct Image *FillImage,*FrameImage,*TextImage;
  360.                 WORD Width,Height,Left,Top;
  361.                 struct Image *DepthImage;
  362.                 LONG FullTitleWidth;
  363.                 ULONG DepthWidth;
  364.  
  365.                     /* Before we do anything else, set up the */
  366.                     /* full width of the window title; this includes */
  367.                     /* both the text and the depth arrangement gadget */
  368.  
  369.                 if(Title)
  370.                     FullTitleWidth = TextLength(&Screen->RastPort,Title,strlen(Title));
  371.                 else
  372.                     FullTitleWidth = 0;
  373.  
  374.                     /* Get the width of the window depth gadget for this screen */
  375.  
  376.                 if(DepthImage = NewObject(NULL,SYSICLASS,
  377.                     SYSIA_Size,        (Screen->Flags & SCREENHIRES) ? SYSISIZE_MEDRES : SYSISIZE_LOWRES,
  378.                     SYSIA_Which,    DEPTHIMAGE,
  379.                     SYSIA_DrawInfo,    DrawInfo,
  380.                 TAG_DONE))
  381.                 {
  382.                     GetAttr(IA_Width,DepthImage,&DepthWidth);
  383.  
  384.                     DisposeObject(DepthImage);
  385.                 }
  386.                 else
  387.                     DepthWidth = (Screen->Flags & SCREENHIRES) ? 23 : 17;
  388.  
  389.                 FullTitleWidth += DepthWidth + 2;
  390.  
  391.                 if(FullTitleWidth > Screen->Width)
  392.                     FullTitleWidth = Screen->Width;
  393.  
  394.                     /* Increase the size to fit all the buttons into the window */
  395.  
  396.                 if(FullButtonWidth > FullTitleWidth)
  397.                     FullTitleWidth = FullButtonWidth;
  398.  
  399.                     /* Height of each line */
  400.  
  401.                 MoreData[4] = Font->tf_YSize;
  402.  
  403.                     /* Pointer to screen rastport used for measuring the text */
  404.  
  405.                 MoreData[6] = (LONG)&Screen->RastPort;
  406.  
  407.                     /* Now do the magic formatting... */
  408.  
  409.                 va_start(VarArgs,FormatString);
  410.  
  411.                 #ifdef USE_GLUE
  412.                     RawDoFmt(FormatString,(APTR)VarArgs,(PUTCHAR)CustomStuffTextGlue,(APTR)MoreData);
  413.                 #else
  414.                     RawDoFmt(FormatString,(APTR)VarArgs,(PUTCHAR)CustomStuffText,(APTR)MoreData);
  415.                 #endif    /* USE_GLUE */
  416.  
  417.                 va_end(VarArgs);
  418.  
  419.                     /* The maximum width of all lines is now in MoreData[5], */
  420.                     /* the effective height of the block in MoreData[3]; */
  421.  
  422.                 TextImage = NewObject(NULL,ITEXTICLASS,
  423.                     IA_FGPen,        DrawInfo->dri_Pens[TEXTPEN],
  424.                     IA_Data,        BodyText,
  425.                     IA_Width,        MoreData[5] + 2*DistX,    /* Add a little room around the text */
  426.                     IA_Height,        MoreData[3] + 2*DistY,
  427.                 TAG_DONE);
  428.  
  429.                     /* Build the checkered background fill pattern */
  430.  
  431.                 FillImage = NewObject(NULL,FILLRECTCLASS,
  432.                     IA_APattern,    &Crosshatch,
  433.                     IA_APatSize,    1,
  434.                     IA_Mode,        JAM2,
  435.                     IA_FGPen,        DrawInfo->dri_Pens[SHINEPEN],
  436.                     IA_BGPen,        DrawInfo->dri_Pens[BACKGROUNDPEN],
  437.                 TAG_DONE);
  438.  
  439.                     /* Do the same for the frame around the text */
  440.  
  441.                 FrameImage = NewObject(NULL,FRAMEICLASS,
  442.                     IA_Recessed,    TRUE,
  443.                 TAG_DONE);
  444.  
  445.                     /* Did we get 'em all? */
  446.  
  447.                 if(FillImage && FrameImage && TextImage)
  448.                 {
  449.                     LONG WindowLeft,WindowTop;
  450.                     struct IBox FramedSize;
  451.                     struct Window *Window;
  452.                     struct Gadget Dummy;
  453.  
  454.                         /* We'll need these offsets pretty soon */
  455.  
  456.                     WindowLeft    = Screen->WBorLeft;
  457.                     WindowTop    = Screen->WBorTop + Screen->Font->ta_YSize + 1;
  458.  
  459.                         /* Now check how large the surrounding frame would be */
  460.  
  461.                     DoMethod((Object *)FrameImage,IM_FRAMEBOX,&TextImage->LeftEdge,&FramedSize,DrawInfo,NULL);
  462.  
  463.                         /* Pad the space around the frame a bit */
  464.  
  465.                     FramedSize.Width    += 2 * RoomX;
  466.                     FramedSize.Height    += 2 * RoomY;
  467.  
  468.                         /* Save these for the window open stuff */
  469.  
  470.                     Width    = WindowLeft +    FramedSize.Width +    Screen->WBorRight;
  471.                     Height    = WindowTop +    FramedSize.Height +    Screen->WBorBottom;
  472.  
  473.                         /* If the window title won't fit on the screen, */
  474.                         /* expand the fillimage a bit; do the same to the */
  475.                         /* textimage. */
  476.  
  477.                     if(Width < FullTitleWidth)
  478.                     {
  479.                         LONG Adapt = (FullTitleWidth - Width + 1) & ~1;
  480.  
  481.                         FramedSize.Width    += Adapt;
  482.                         Width                += Adapt;
  483.  
  484.                         DistX                += Adapt / 2;
  485.  
  486.                         SetAttrs((Object *)TextImage,
  487.                             IA_Width,MoreData[5] + 2*DistX,
  488.                         TAG_DONE);
  489.                     }
  490.  
  491.                         /* Adjust size and position of the background pattern */
  492.  
  493.                     SetAttrs((Object *)FillImage,
  494.                         IA_Left,    WindowLeft,
  495.                         IA_Top,        WindowTop,
  496.                         IA_Width,    FramedSize.Width,
  497.                         IA_Height,    FramedSize.Height,
  498.                     TAG_DONE);
  499.  
  500.                         /* Do the whole thing all over again for the framed text; */
  501.                         /* this will put the right coords to centre the text within */
  502.                         /* the frame into FramedSize */
  503.  
  504.                     DoMethod((Object *)FrameImage,IM_FRAMEBOX,&TextImage->LeftEdge,&FramedSize,DrawInfo,FRAMEF_SPECIFY);
  505.  
  506.                         /* Move the text around */
  507.  
  508.                     SetAttrs((Object *)TextImage,
  509.                         IA_Left,    WindowLeft    - FramedSize.Left    + DistX,
  510.                         IA_Top,        WindowTop    - FramedSize.Top    + DistY,
  511.                     TAG_DONE);
  512.  
  513.                         /* Almost finished, now centre the frame around the text */
  514.  
  515.                     DoMethod((Object *)FrameImage,IM_FRAMEBOX,&TextImage->LeftEdge,&FramedSize,DrawInfo,NULL);
  516.  
  517.                     SetAttrs((Object *)FrameImage,
  518.                         IA_Left,    FramedSize.Left        - DistX,
  519.                         IA_Top,        FramedSize.Top        - DistY,
  520.                         IA_Width,    FramedSize.Width,
  521.                         IA_Height,    FramedSize.Height,
  522.                     TAG_DONE);
  523.  
  524.                         /* Now link the objects together */
  525.  
  526.                     FillImage->NextImage    = FrameImage;
  527.                     FrameImage->NextImage    = TextImage;
  528.  
  529.                         /* Zap the dummy gadget and put the image inside */
  530.  
  531.                     memset(&Dummy,0,sizeof(Dummy));
  532.  
  533.                     Dummy.Flags            = GFLG_GADGIMAGE|GFLG_GADGHNONE;
  534.                     Dummy.GadgetRender    = FillImage;
  535.  
  536.                         /* Put the gadget in */
  537.  
  538.                     /* ALWAYS */
  539.                     {
  540.                         LONG LocalLeft    = FrameImage->LeftEdge;
  541.                         LONG LocalTop    = FillImage->TopEdge + FillImage->Height;
  542.  
  543.                         GadgetTable[GadgetInformation[1] - 1]->NextGadget = &Dummy;
  544.  
  545.                         SetAttrs((Object *)FillImage,
  546.                             IA_Height,    FillImage->Height + GadgetTable[0]->Height + RoomY,
  547.                         TAG_DONE);
  548.  
  549.                         Height += GadgetTable[0]->Height + RoomY;
  550.  
  551.                         if(GadgetInformation[1] > 1)
  552.                         {
  553.                             LONG Room,Count,i;
  554.  
  555.                             Room         = Width - FullButtonWidth;
  556.                             Count         = GadgetInformation[1] - 1;
  557.                             LocalLeft     = FrameImage->LeftEdge;
  558.                             Room        += Count * RoomX;
  559.  
  560.                             for(i = 0 ; i <= Count ; i++)
  561.                             {
  562.                                 SetAttrs((Object *)GadgetTable[i],
  563.                                     GA_Top,        LocalTop,
  564.                                     GA_Left,    LocalLeft,
  565.                                 TAG_DONE);
  566.  
  567.                                 LocalLeft += GadgetTable[i]->Width + ((Room * (i + 1)) / Count - (Room * i) / Count);
  568.                             }
  569.                         }
  570.                         else
  571.                         {
  572.                             SetAttrs((Object *)GadgetTable[0],
  573.                                 GA_Top,        LocalTop,
  574.                                 GA_Left,    LocalLeft + (FillImage->Width - GadgetTable[0]->Width) / 2,
  575.                             TAG_DONE);
  576.                         }
  577.                     }
  578.  
  579.                         /* Check if the window will fit on the screen */
  580.  
  581.                     if(Width <= Screen->Width && Height <= Screen->Height)
  582.                     {
  583.                             /* Centre the body text strings */
  584.  
  585.                         /* ALWAYS */
  586.                         {
  587.                             struct IntuiText *This;
  588.  
  589.                             for(This = BodyText ; This ; This = This->NextText)
  590.                             {
  591.                                 This->ITextFont = Screen->Font;
  592.                                 This->LeftEdge = (MoreData[5] - IntuiTextLength(This)) / 2;
  593.                                 This->ITextFont = NULL;
  594.                             }
  595.                         }
  596.  
  597.                             /* Centre the window to open */
  598.  
  599.                         if(Parent)
  600.                         {
  601.                             WindowLeft        = Parent->LeftEdge + Parent->BorderLeft;
  602.                             WindowTop        = Parent->TopEdge + Parent->BorderTop;
  603.                             WindowWidth        = Parent->Width - (Parent->BorderLeft + Parent->BorderRight);
  604.                             WindowHeight    = Parent->Height - (Parent ->BorderTop + Parent->BorderBottom);
  605.  
  606.                             if((Left = WindowLeft + (WindowWidth - Width) / 2) < 0)
  607.                                 Left = 0;
  608.  
  609.                             if((Top = WindowTop + (WindowHeight - Height) / 2) < 0)
  610.                                 Top = 0;
  611.  
  612.                             GetScreenInfo(Screen,&ScreenLeft,&ScreenTop,&ScreenWidth,&ScreenHeight);
  613.  
  614.                             if(Left < ScreenLeft || Left + Width > ScreenLeft + ScreenWidth)
  615.                                 Left = -1;
  616.  
  617.                             if(Top < ScreenTop || Top + Height > ScreenTop + ScreenHeight)
  618.                                 Top = -1;
  619.  
  620.                             if(Top == -1 || Left == -1)
  621.                                 CentreWindow(Screen,Width,Height,&Left,&Top);
  622.                         }
  623.                         else
  624.                             CentreWindow(Screen,Width,Height,&Left,&Top);
  625.  
  626.                             /* Finally, open the window */
  627.  
  628.                         if(Window = OpenWindowTags(NULL,
  629.                             WA_Left,            Left,
  630.                             WA_Top,                Top,
  631.                             WA_Width,            Width,
  632.                             WA_Height,            Height,
  633.                             WA_Title,            Title,
  634.                             WA_Flags,            WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_RMBTRAP | WFLG_NOCAREREFRESH | WFLG_SIMPLE_REFRESH | WFLG_ACTIVATE,
  635.                             WA_IDCMP,            IDCMP_GADGETUP | IDCMP_VANILLAKEY | IDCMP_RAWKEY,
  636.                             WA_CustomScreen,    Screen,
  637.                             WA_Gadgets,            GadgetTable[0],
  638.                         TAG_DONE))
  639.                         {
  640.                             struct IntuiMessage    *Message;
  641.                             struct Gadget *MsgGadget;
  642.                             struct Gadget *Gadget;
  643.                             BOOL Terminated;
  644.                             ULONG MsgClass;
  645.                             LONG MsgCode;
  646.  
  647.                             Gadget        = NULL;
  648.                             Terminated    = FALSE;
  649.  
  650.                             do
  651.                             {
  652.                                 WaitPort(Window->UserPort);
  653.  
  654.                                 while(Message = (struct IntuiMessage *)GetMsg(Window->UserPort))
  655.                                 {
  656.                                     MsgClass    = Message->Class;
  657.                                     MsgCode        = Message->Code;
  658.                                     MsgGadget    = Message->IAddress;
  659.  
  660.                                     ReplyMsg((struct Message *)Message);
  661.  
  662.                                     switch(MsgClass)
  663.                                     {
  664.                                         case IDCMP_GADGETUP:
  665.  
  666.                                             Terminated    = TRUE;
  667.                                             Result        = MsgGadget->GadgetID;
  668.  
  669.                                             break;
  670.  
  671.                                         case IDCMP_VANILLAKEY:
  672.  
  673.                                             MsgCode = ToUpper(MsgCode);
  674.  
  675.                                             switch(MsgCode)
  676.                                             {
  677.                                                 case '\033':
  678.                                                 case 'B':
  679.                                                 case CONTROL_('C'):
  680.  
  681.                                                     Terminated    = TRUE;
  682.                                                     Gadget        = GadgetTable[GadgetInformation[1] - 1];
  683.  
  684.                                                     break;
  685.  
  686.                                                 case '\r':
  687.                                                 case 'V':
  688.  
  689.                                                     Terminated    = TRUE;
  690.                                                     Gadget        = GadgetTable[0];
  691.  
  692.                                                     break;
  693.                                             }
  694.  
  695.                                             break;
  696.  
  697.                                         case IDCMP_RAWKEY:
  698.  
  699.                                             switch(MsgCode)
  700.                                             {
  701.                                                 case HELP_CODE:
  702.  
  703.                                                     GuideDisplay(CONTEXT_MAIN);
  704.                                                     break;
  705.  
  706.                                                 default:
  707.  
  708.                                                     if(MsgCode >= F01_CODE && MsgCode <= F10_CODE)
  709.                                                     {
  710.                                                         MsgCode -= F01_CODE;
  711.  
  712.                                                         if(MsgCode < GadgetInformation[1])
  713.                                                         {
  714.                                                             Terminated = TRUE;
  715.  
  716.                                                             Gadget = GadgetTable[MsgCode];
  717.                                                         }
  718.                                                     }
  719.  
  720.                                                     break;
  721.                                             }
  722.  
  723.                                             break;
  724.                                     }
  725.                                 }
  726.                             }
  727.                             while(!Terminated);
  728.  
  729.                             if(Gadget)
  730.                             {
  731.                                 STATIC ULONG SelectedTags[]        = { GA_Selected,TRUE,    TAG_DONE };
  732.                                 STATIC ULONG DeselectedTags[]    = { GA_Selected,FALSE,    TAG_DONE };
  733.  
  734.                                 SetGadgetAttrsA(Gadget,Window,NULL,(struct TagItem *)SelectedTags);
  735.                                 RefreshGList(Gadget,Window,NULL,1);
  736.  
  737.                                 DelayTime(0,80000);
  738.  
  739.                                 SetGadgetAttrsA(Gadget,Window,NULL,(struct TagItem *)DeselectedTags);
  740.                                 RefreshGList(Gadget,Window,NULL,1);
  741.                             }
  742.  
  743.                             CloseWindow(Window);
  744.                         }
  745.                     }
  746.                 }
  747.  
  748.                     /* Get rid of the images */
  749.  
  750.                 DisposeObject(FillImage);
  751.                 DisposeObject(FrameImage);
  752.                 DisposeObject(TextImage);
  753.             }
  754.  
  755.                 /* And the buffers so much work went into... */
  756.  
  757.             FreeVec(BodyText);
  758.             FreeVec(GadgetText);
  759.  
  760.             if(GadgetTable)
  761.             {
  762.                 LONG i;
  763.  
  764.                 for(i = 0 ; i < GadgetInformation[1] ; i++)
  765.                     DisposeObject(GadgetTable[i]);
  766.  
  767.                 FreeVec(GadgetTable);
  768.             }
  769.  
  770.             DisposeObject(GadgetFrameImage);
  771.  
  772.             FreeScreenDrawInfo(Screen,DrawInfo);
  773.         }
  774.  
  775.         if(PopBack)
  776.             ScreenToBack(Screen);
  777.  
  778.         if(!Parent)
  779.             UnlockPubScreen(NULL,Screen);
  780.     }
  781.  
  782.     return(Result);
  783. }
  784.